#include "complex.h"
#include <cassert>
#include "moremath.h"

namespace moremath {

//double& complex::operator[] (int i){
//	assert(i==0 || i==1);
//	if(i==0) return mReal;
//	if(i==1) return mImag;
//}

void complex::operator =(complex q){
	mReal = q.re();
	mImag = q.im();
}

complex complex::operator +(complex q){
	complex temp;
	temp.re() = mReal + q.re();
	temp.im() = mImag + q.im();
	return temp;
}

void complex::operator += (complex q){
	mReal += q.re();
	mImag += q.im();
}

complex complex::operator -(){
	complex temp;
	temp.re() = -mReal;
	temp.im() = -mImag;
	return temp;
}

complex complex::operator -(complex _c){
	complex temp;
	temp.re() = mReal - _c.re();
	temp.im() = mImag - _c.im();
	return temp;
}

complex complex::operator *(complex q){
	complex temp;
	temp.re() = mReal*q.re() - mImag*q.im();
	temp.im() = mImag*q.re() + mReal*q.im();
	return temp;
}

void complex::operator *=(double s){
	mReal = mReal*s;
	mImag = mImag*s;
}

void complex::operator *=(complex q){
	*this = *this*q;
}

complex complex::operator *(double n){
	complex temp;
	temp.re() = mReal*n;
	temp.im() = mImag*n;
	return temp;
}

complex complex::operator /(double n){
	complex temp;
	temp.re() = mReal/n;
	temp.im() = mImag/n;
	return temp;
}

complex complex::inv(){
	double d = sqr(mReal) + sqr(mImag);
	return complex(mReal/d, -mImag/d);
}

complex complex::operator /(complex _c){
	return (*this)*_c.inv();
}

double complex::norm(){
	return sqrt(mReal*mReal + mImag*mImag);	
}

complex complex::conj(){
	complex temp;
	temp.re() = mReal;
	temp.im() = -mImag;
	return temp;
}
}

ostream& operator <<(ostream &out, moremath::complex &_c){
	out<<"("<<_c.re()<<", "<<_c.im()<<")";
	return out;
}

moremath::complex exp(moremath::complex q){
	return moremath::complex(cos(q.im()), sin(q.im()))*exp(q.re());
}

moremath::complex sqrt(moremath::complex q){
	double t1 = sqrt(sqr(q.re()) + sqr(q.im()));
	return moremath::complex(sqrt((t1+q.re())/2), sqrt((t1-q.re())/2));
}
